﻿using System;
using System.IO;
using gixoom.Dom.Score;

namespace gixoom.Dom
{
    internal static class Ensure
    {
        internal static void ArgumentNotNull(object argument, string name)
        {
            if (argument == null)
            {
                throw new ArgumentNullException(name, "Cannot be null");
            }
        }

        internal static void StringArgumentNotEmpty(string argument, string name)
        {
            if (argument == string.Empty)
            {
                throw new ArgumentException("String argument cannot be empty", name);
            }
        }

        internal static void ArrayLengthIsValid<T>(T[] argument, int validLength, string name)
        {
            if (argument.Length != validLength)
            {
                throw new ArgumentException("Array length " + argument.Length +
                    " is not valid. Valid one is " + validLength, name);
            }
        }

        internal static void Sha512HashStringIsValid(string argument,
            ISha512StringValidator validator, string name)
        {
            if (!validator.IsValid(argument))
            {
                throw new ArgumentException("SHA512 hash string is not valid.", name);
            }
        }

        internal static void StreamCanBeRead(Stream stream, string argumentName)
        {
            if (!stream.CanRead)
            {
                throw new ArgumentException("Stream cannot be read.", argumentName);
            }
        }

        internal static void StreamCanBeSought(Stream stream, string argumentName)
        {
            if (!stream.CanSeek)
            {
                throw new ArgumentException("Stream cannot be sought.", argumentName);
            }
        }

        internal static void IntGreaterThanZero(int argument, string name)
        {
            if (argument <= 0)
            {
                throw new ArgumentOutOfRangeException(name, name + " parameter should be greater than zero.");
            }
        }

        internal static void IndexWithinRange<T>(int indexArgument, T[] array, string argumentName)
        {
            if (indexArgument < 0 || indexArgument >= array.Length)
            {
                throw new ArgumentOutOfRangeException(argumentName, "There are " + array.Length +
                    " items in the array. " + argumentName + " parameter should fall into range 0.." +
                    (array.Length - 1));
            }
        }

        internal static void OffsetAndCountAreValid<T>(int offset, int count, T[] array,
            string countArgumentName, string arrayArgumentName)
        {
            if ((offset + count) > array.Length)
            {
                throw new ArgumentException(countArgumentName + " is an invalid value or " +
                    arrayArgumentName + " length is invalid.");
            }
        }

        internal static void EnoughItems<T>(T[] array, int minimumCount, string arrayArgumentName)
        {
            if (array.Length < minimumCount)
            {
                throw new ArgumentException("The " + arrayArgumentName + " contains " +
                    array.Length + " elements. There should be at least " + minimumCount + ".");
            }
        }

        internal static void EnoughItemsTillEnd<T>(T[] array, int arrayIndex, int minimumCountTillEnd,
            string offsetArgumentName, string arrayArgumentName)
        {
            if ((array.Length - arrayIndex) < minimumCountTillEnd)
            {
                throw new ArgumentException(offsetArgumentName, " is an invalid value or " +
                    arrayArgumentName + " length is invalid.");
            }
        }
    }
}
